home *** CD-ROM | disk | FTP | other *** search
- /* Functions for copying files.
-
- 93/12/02 aih
- - removed calls to task library so i won't have to support them
-
- 93/10/23 aih
- - resource fork is copied only if it exists
-
- 93/10/13 AIH
- - Added calls to task library while copying files
- - the file's catalog information is copied along with the file
-
- 92/11/06 AIH
- - Added FileReadNoError and FileCopyForkNoError to recover a file
- on a floppy with a couple of damaged logical blocks
-
- 91/05/17 AIH
- - To allow the File Manager to automatically convert '\r' into '\n'
- and vice versa when copying to or from an A/UX volume, the destination
- file's creator and type are set immediately when it is created,
- instead of after the copy (see TN229).
-
- 91/05/06 Ari Halberstadt (AIH)
- - Fixed mistake in FileCopyData (attempted to truncate the destination
- file before the file had been opened).
- - Fixed mistake in FileCopyFork (never noticed EOF) */
-
- #include <limits.h>
- #include <string.h>
- #include "FileLib.h"
- #include "MathLib.h"
- #include "MemoryLib.h"
- #include "ResourceLib.h"
- #include "StringLib.h"
-
- /* Files are stored in logical blocks of 512 bytes (IM-IV, 89).
- When there's an error in a certain logical block, it's probably
- necessary to skip that entire block. At least, that was my
- experience with an I/O error on a floppy. */
- #define LOGICAL_BLOCK (512)
-
- /* read a logical block from the file and ignore ioErr errors */
- static FilePosType FileReadNoError(FileType *fp, char buffer[LOGICAL_BLOCK])
- {
- FilePosType startpos = 0;
- FilePosType endpos = 0;
- FilePosType count = 0;
- volatile Boolean failed = false;
-
- TRY {
- if (! failed) {
- startpos = FilePosition(fp);
- count = FileRead(fp, LOGICAL_BLOCK, buffer);
- }
- else {
- /* Skip this damaged logical block. Replace unreadable bytes
- with nil bytes in the buffer. */
- endpos = min(startpos + LOGICAL_BLOCK, FileSize(fp));
- FileSeek(fp, fsFromStart, endpos);
- memclr(buffer, LOGICAL_BLOCK);
- }
- ensure(FilePosition(fp) == min(startpos + LOGICAL_BLOCK, FileSize(fp)));
- } CATCH {
- if (FailReason() == ioErr) {
- failed = true;
- RETRY;
- }
- } ENDTRY;
- return(count);
- }
-
- /* copy either fork of a file, ignoring ioErr in source file (replaces
- damaged blocks with nils) */
- static void FileCopyForkNoError(FileType *src, FileType *dst)
- {
- FilePosType count;
- char buf[LOGICAL_BLOCK];
-
- do {
- count = FileReadNoError(src, buf);
- if (count > 0)
- FileWrite(dst, count, buf);
- } while (count > 0);
- }
-
- /* copy either fork of a file */
- void FileCopyFork(FileType *src, FileType *dst)
- {
- FilePosType count = 0;
- FilePosType bufsz = FILE_BUFSIZ;
- volatile char smallbuf[FILE_BUFSIZ];
- volatile char *buf = smallbuf;
-
- TRY {
- if (MemAvailable(FileSize(src))) {
- bufsz = FileSize(src);
- buf = PtrBegin(bufsz);
- }
- do {
- count = FileRead(src, bufsz, buf);
- if (count > 0)
- FileWrite(dst, count, buf);
- } while (count > 0);
- } CLEANUP {
- if (buf != smallbuf)
- PtrEnd(buf);
- } ENDTRY;
- }
-
- /* Copy the data fork of the source file to the data fork of the
- destination file. */
- void FileCopyData(FileType *src, FileType *dst)
- {
- require(! FilesAreSame(src, dst));
- TRY {
- FileOpen(src, fsRdPerm);
- FileOpen(dst, fsWrPerm);
- FileResize(dst, 0);
- FileCopyFork(src, dst);
- } CLEANUP {
- FileClose(src);
- FileClose(dst);
- } ENDTRY;
- }
-
- /* Copy the resource fork of the source file to the resource fork of the
- destination file. */
- void FileCopyRes(FileType *src, FileType *dst)
- {
- require(! FilesAreSame(src, dst));
- TRY {
- FileOpenRes(src, fsRdPerm);
- FileOpenRes(dst, fsWrPerm);
- FileCopyFork(src, dst);
- } CLEANUP {
- FileClose(dst);
- FileClose(src);
- } ENDTRY;
- }
-
- /* Copy both forks and the Finder and catalog information of the source
- file to the destination file. */
- void FileCopy(FileType *src, FileType *dst)
- {
- volatile Boolean created = false;
- CInfoPBRec cat;
-
- TRY {
- FileCatalog(src, &cat);
- FileCreate(dst, cat.hFileInfo.ioFlFndrInfo.fdCreator,
- cat.hFileInfo.ioFlFndrInfo.fdType);
- created = true;
- FileCopyData(src, dst);
- if (ResFileExists(src)) {
- HCreateResFile(dst->vol, dst->dir, dst->pnm);
- FailResError();
- FileCopyRes(src, dst);
- }
- FileCatalogSet(dst, &cat);
- } CATCH {
- if (created)
- FileDelete(dst);
- } ENDTRY;
- }
-